package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.model.dto.OrderDTO;
import cn.edu.tju.elm.service.OrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/orders")
@Tag(name = "管理订单", description = "对订单进行增删改查")
public class OrderController {
    @Autowired
    private UserService userService;

    @Autowired
    private OrderService orderService;
    
    // 添加日志记录器
    private static final Logger log = LoggerFactory.getLogger(OrderController.class);

    @PostMapping(value = "")
    @Operation(summary = "创建订单", description = "创建新的订单")
    public HttpResult<OrderDTO> addOrders(@RequestBody Order order) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new RuntimeException("用户未登录"));
            
            // 创建订单
            Order savedOrder = orderService.createOrder(order, currentUser);
            
            // 转换为 DTO 并返回，避免循环引用
            OrderDTO orderDTO = orderService.getOrderDTOById(savedOrder.getId(), currentUser);
            return HttpResult.success(orderDTO);
        } catch (RuntimeException e) {
            // 提供更友好的错误消息
            if (e.getMessage().contains("商家不存在")) {
                return HttpResult.failure(ResultCodeEnum.PARAM_ERROR, e.getMessage());
            } else if (e.getMessage().contains("配送地址不存在")) {
                return HttpResult.failure(ResultCodeEnum.PARAM_ERROR, e.getMessage());
            } else if (e.getMessage().contains("无权")) {
                return HttpResult.failure(ResultCodeEnum.FORBIDDEN, e.getMessage());
            }
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "创建订单失败: " + e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "创建订单失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @Operation(summary = "获取订单详情", description = "根据ID获取订单详情")
    public HttpResult<OrderDTO> getOrderById(
            @Parameter(description = "订单ID", required = true) @PathVariable Long id) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new RuntimeException("用户未登录"));
            
            OrderDTO orderDTO = orderService.getOrderDTOById(id, currentUser);
            if (orderDTO != null) {
                return HttpResult.success(orderDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "订单不存在或无权访问");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "获取订单失败: " + e.getMessage());
        }
    }

    @GetMapping("")
    @Operation(summary = "获取用户订单列表", description = "根据用户ID获取订单列表（管理员权限）")
    public HttpResult<List<OrderDTO>> listOrdersByUserId(
            @Parameter(description = "用户ID", required = false) @RequestParam(required = false) Long userId) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new RuntimeException("用户未登录"));
            
            // 如果没有提供userId，默认获取当前用户的订单
            if (userId == null) {
                List<Order> orders = orderService.findByCustomer(currentUser);
                // 转换为DTO列表
                List<OrderDTO> orderDTOs = orders.stream()
                        .map(order -> orderService.getOrderDTOById(order.getId(), currentUser))
                        .collect(java.util.stream.Collectors.toList());
                return HttpResult.success(orderDTOs);
            }
            
            // 如果提供了userId，但userId等于当前用户的ID，则允许查看自己的订单
            if (currentUser.getId() != null && userId.equals(currentUser.getId())) {
                List<Order> orders = orderService.findByCustomerId(userId);
                // 转换为DTO列表
                List<OrderDTO> orderDTOs = orders.stream()
                        .map(order -> orderService.getOrderDTOById(order.getId(), currentUser))
                        .collect(java.util.stream.Collectors.toList());
                return HttpResult.success(orderDTOs);
            }
            
            // 如果提供了userId并且不等于当前用户ID，检查当前用户是否有权限查看其他用户的订单
            boolean hasPermission = false;
            try {
                hasPermission = currentUser.hasPermissionToViewOtherOrders();
            } catch (Exception e) {
                log.error("检查用户权限时出错", e);
                return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "权限检查失败");
            }
            
            if (!hasPermission) {
                return HttpResult.failure(ResultCodeEnum.FORBIDDEN, "无权查看其他用户的订单");
            }
            
            // 获取指定用户的订单
            List<Order> orders = orderService.findByCustomerId(userId);
            // 转换为DTO列表
            List<OrderDTO> orderDTOs = orders.stream()
                    .map(order -> orderService.getOrderDTOById(order.getId(), currentUser))
                    .collect(java.util.stream.Collectors.toList());
            return HttpResult.success(orderDTOs);
        } catch (RuntimeException e) {
            if (e.getMessage().contains("用户未登录")) {
                return HttpResult.failure(ResultCodeEnum.UNAUTHORIZED, e.getMessage());
            }
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "获取订单列表失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("获取订单列表时发生未知错误", e);
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "系统内部错误，请稍后重试");
        }
    }

    

    @DeleteMapping("/{id}")
    @Operation(summary = "删除订单", description = "删除指定ID的订单")
    public HttpResult<String> deleteOrder(
            @Parameter(description = "订单ID", required = true) @PathVariable Long id) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new RuntimeException("用户未登录"));
            
            // 删除订单
            orderService.deleteOrder(id, currentUser);
            return HttpResult.success("订单删除成功");
        } catch (RuntimeException e) {
            if (e.getMessage().contains("无权") || e.getMessage().contains("不存在")) {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, e.getMessage());
            }
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除订单失败: " + e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除订单失败: "+ e.getMessage());
        }
    }
    

    @PostMapping("/{id}/simulate-payment")
    @Operation(summary = "模拟支付成功", description = "用于测试和演示，将订单状态从未支付更新为已支付，不调用真实支付网关")
    public HttpResult<OrderDTO> simulatePayment(
            @Parameter(description = "订单ID", required = true) @PathVariable Long id) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new RuntimeException("用户未登录"));
            
            // 调用模拟支付服务
            Order paidOrder = orderService.simulatePayment(id, currentUser);
            
            // 转换为 DTO 并返回
            OrderDTO orderDTO = orderService.getOrderDTOById(paidOrder.getId(), currentUser);
            return HttpResult.success(orderDTO);
            
        } catch (RuntimeException e) {
            // 提供更友好的错误消息
            if (e.getMessage().contains("无权")) {
                return HttpResult.failure(ResultCodeEnum.FORBIDDEN, e.getMessage());
            } else if (e.getMessage().contains("不允许支付")) {
                return HttpResult.failure(ResultCodeEnum.PARAM_ERROR, e.getMessage());
            }
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "模拟支付失败: " + e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "模拟支付失败: " + e.getMessage());
        }
    }
}